#include "IDLParser.h"
#include "Ast.h"
#include "SyntaxCheckerVisitor.h"
#include "CLangTypeHeaderVisitor.h"
#include "CLangTypeSourceVisitor.h"
#include "CLangTypeSupportHeaderVisitor.h"
#include "CLangTypeSupportSourceVisitor.h"
#include "CppLangTypeHeaderVisitor.h"
#include "CppLangTypeSourceVisitor.h"
#include "CppLangTypeSupportHeaderVisitor.h"
#include "CppLangTypeSupportSourceVisitor.h"
#include "Ros2TransformerVisitor.h"
#include "SWIGJavaInterfaceFileVisitor.h"
#include "SWIGJavaCMakeListsFileVisitor.h"
#include "SWIGPythonInterfaceFileVisitor.h"
#include "SWIGPythonCMakeListsFileVisitor.h"
#include "RustCargoTomlFileVisitor.h"
#include "RustBuildFileVisitor.h"
#include "Ros2RpcTransformerVisitor.h"
#include "IDLBison.hpp"
#include <fstream>
#include <iostream>
#include <sstream>


typedef struct yy_buffer_state* YY_BUFFER_STATE;
extern YY_BUFFER_STATE yy_scan_string(const char* str);

#if YYDEBUG
extern int yydebug;
#endif

extern int yylineno;

SpecificationNode *IDLParser::parse(const std::string &idlPath) {
#if YYDEBUG
    yydebug = 1;
#endif
    std::ifstream file(idlPath);
    if (!file.is_open()) {
        std::cerr << "Could not open file: " << idlPath << std::endl;
        return nullptr;
    }
    std::stringstream buffer;
    buffer << file.rdbuf();
    std::string idlContent = buffer.str();
    // 将">>"替换为"> >"
    size_t pos = 0;
    while ((pos = idlContent.find(">>", pos)) != std::string::npos) {
        idlContent.replace(pos, 2, "> >");
        pos += 2; // Move past the newly inserted characters
    }
    // Set up the input for the parser
    yy_scan_string(idlContent.c_str());
    yylineno = 1;  // 重置行号为1

    // Parse the IDL content
    SpecificationNode* root = nullptr;
    if (yyparse() == 0) {
        root = SpecificationNode::get_instance();
    } else {
        std::cerr << "Failed to parse IDL file " << idlPath << std::endl;
        exit(-1);
    }

    // ros transform add ros2 namespace
    if (params_.has("ros2")) {
        Ros2TransformerVisitor ros2TransformerVisitor;
        root->accept(ros2TransformerVisitor);
    }

    // ros rpc transform
    if (params_.has("rpc")) {
        Ros2RpcTransformerVisitor ros2RpcTransformerVisitor;
        root->accept(ros2RpcTransformerVisitor);
    }

    // 语法检查
    SyntaxCheckerVisitor syntaxCheckerVisitor(params_.getIncludePaths());
    root->accept(syntaxCheckerVisitor);

    std::string dstPath = params_.get("output_dir");;
    std::string language = params_.get("language");
    std::string fileNameBase = idlPath;
    // IDL名称去掉后缀作为文件名
    pos = idlPath.find_last_of(".");
    if (pos != std::string::npos) {
        fileNameBase = fileNameBase.substr(0, pos);
    }
    // IDL名称去掉路径作为文件名
    pos = fileNameBase.find_last_of("/");
    if (pos != std::string::npos) {
        fileNameBase = fileNameBase.substr(pos + 1);
    }
    if (language == "c" || language == "rust") {
        // C类型名称Visitor
        CLangTypeNameVisitor cTypeNameVisitor(syntaxCheckerVisitor, *this);
        root->accept(cTypeNameVisitor);
        // 生成C头文件定义
        CLangTypeHeaderVisitor cTypeHeaderVisitor(dstPath, fileNameBase + ".h", &cTypeNameVisitor);
        root->accept(cTypeHeaderVisitor);

        // 生成C源文件定义
        CLangTypeSourceVisitor cTypeSourceVisitor(dstPath, fileNameBase + ".cpp", &cTypeNameVisitor, &cTypeHeaderVisitor);
        root->accept(cTypeSourceVisitor);

        // 生成C的TypeSupport头文件
        CLangTypeSupportHeaderVisitor cTypeSupportHeaderVisitor(dstPath, fileNameBase + "TypeSupport.h", &cTypeNameVisitor);
        root->accept(cTypeSupportHeaderVisitor);

        // 生成C的TypeSupport源文件
        CLangTypeSupportSourceVisitor cTypeSupportSourceVisitor(dstPath, fileNameBase + "TypeSupport.cpp", &cTypeNameVisitor, cTypeHeaderVisitor.getFileName());
        root->accept(cTypeSupportSourceVisitor);

        if (language == "rust") {
            // 生成Rust的Cargo.toml文件
            RustCargoTomlFileVisitor rustCargoTomlFileVisitor(dstPath, fileNameBase, &cTypeNameVisitor, &cTypeHeaderVisitor);
            root->accept(rustCargoTomlFileVisitor);

            // 生成Rust的build.rs文件
            RustBuildFileVisitor rustBuildFileVisitor(dstPath, fileNameBase, &cTypeNameVisitor, &cTypeHeaderVisitor);
            root->accept(rustBuildFileVisitor);
        }

    } 
    if (language == "c++" || language == "java" || language == "python") {
        // C++类型名称Visitor
        CppLangTypeNameVisitor cppTypeNameVisitor(syntaxCheckerVisitor, *this);
        root->accept(cppTypeNameVisitor);

        // 生成C++头文件定义
        CppLangTypeHeaderVisitor cppTypeHeaderVisitor(dstPath, fileNameBase + ".h", &cppTypeNameVisitor);
        root->accept(cppTypeHeaderVisitor);

        // 生成C++源文件定义
        CppLangTypeSourceVisitor cppTypeSourceVisitor(dstPath, fileNameBase + ".cpp", &cppTypeNameVisitor, &cppTypeHeaderVisitor);
        root->accept(cppTypeSourceVisitor);

        // 生成c++的TypeSupport头文件
        CppLangTypeSupportHeaderVisitor cppTypeSupportHeaderVisitor(dstPath, fileNameBase + "TypeSupport.h", &cppTypeNameVisitor, cppTypeHeaderVisitor.getFileName());
        root->accept(cppTypeSupportHeaderVisitor);

        // 生成c++的TypeSupport源文件
        CppLangTypeSupportSourceVisitor cppTypeSupportSourceVisitor(dstPath, fileNameBase + "TypeSupport.cpp", &cppTypeNameVisitor, cppTypeSupportHeaderVisitor.getFileName());
        root->accept(cppTypeSupportSourceVisitor);

        if (language == "java") {
            // 生成SWIG接口文件
            SWIGJavaInterfaceFileVisitor swigJavaInterfaceFileVisitor(dstPath, fileNameBase + ".i", &cppTypeNameVisitor, &cppTypeHeaderVisitor);
            root->accept(swigJavaInterfaceFileVisitor);
    
            // 生成CMakeLists文件
            SWIGJavaCMakeListsFileVisitor swigJavaCMakeListsFileVisitor(dstPath, fileNameBase, &cppTypeSourceVisitor, &cppTypeSupportSourceVisitor);
            root->accept(swigJavaCMakeListsFileVisitor);
        }
        if (language == "python") {
            // 生成SWIG接口文件
            SWIGPythonInterfaceFileVisitor swigPythonInterfaceFileVisitor(dstPath, fileNameBase + ".i", &cppTypeNameVisitor, &cppTypeHeaderVisitor);
            root->accept(swigPythonInterfaceFileVisitor);
    
            // 生成CMakeLists文件
            SWIGPythonCMakeListsFileVisitor swigPythonCMakeListsFileVisitor(dstPath, fileNameBase, &cppTypeSourceVisitor, &cppTypeSupportSourceVisitor);
            root->accept(swigPythonCMakeListsFileVisitor);
        }
    }
    return root;
}